"""
    https://binance-docs.github.io/apidocs/spot/cn/#websocket
"""
import json
import logging
import requests
import sys
from datetime import datetime
from websockets.sync.client import connect

logging.basicConfig(
    stream=sys.stdout, level=logging.INFO, format="%(asctime)s-%(levelname)s-%(message)s"
)


class BinanceSpotFeed(object):
    def __init__(self, callback):
        self.callback = callback
        self.symbols = list()

    @staticmethod
    def get_symbols():
        result = list()
        json_data = requests.get("https://data-api.binance.vision/api/v3/exchangeInfo").json()
        for item in json_data["symbols"]:
            if item["status"] == "TRADING" and item["quoteAsset"] == "USDT":
                result.append(item["symbol"])
        return result

    @staticmethod
    def seed_message(ws, message):
        logging.info(f"SendMessage: {message}")
        ws.send(json.dumps(message))

    def on_kline(self, data):
        self.callback({
            "datetime": datetime.fromtimestamp(data["t"] / 1000), "symbol": data["s"],
            "open": float(data["o"]), "high": float(data["h"]), "low": float(data["l"]), "close": float(data["c"]),
            "volume": float(data["v"]), "amount": float(data["q"])
        })

    def on_stream(self, msg):
        if "stream" in msg:
            if "@kline_1m" in msg["stream"]:
                self.on_kline(msg["data"]["k"])

    def on_message(self, ws, msg):
        msg = json.loads(msg)
        self.on_ping(ws, msg)
        self.on_stream(msg)

    def on_open(self, ws):
        self.seed_message(ws, {
            "method": "SUBSCRIBE",
            "params": [f"{symbol.lower()}@kline_1m" for symbol in self.symbols],
            "id": None
        })

    def on_ping(self, ws, msg):
        if "ping" in msg:
            self.seed_message(ws, msg["ping"])

    def start(self):
        self.symbols = self.get_symbols()
        with connect("wss://stream.yshyqxx.com/stream") as ws:
            self.on_open(ws)
            while True:
                message = ws.recv(timeout=60)
                self.on_message(ws, message)
